﻿using System;
using IocPerformance.Classes.Complex;
using IocPerformance.Classes.Dummy;
using IocPerformance.Classes.Generics;
using IocPerformance.Classes.Multiple;
using IocPerformance.Classes.Standard;
using My.Ioc;
using My.Ioc.Extensions.OpenGeneric;

namespace IocPerformance.Adapters
{
    public sealed class MyIocAdapter : ContainerAdapterBase
    {
        private IObjectContainer container;

        public override string PackageName
        {
            get { return "MyIoc"; }
        }

        public override bool SupportsInterception
        {
            get { return false; }
        }

        public override bool SupportGeneric
        {
            get { return true; }
        }

        public override bool SupportsMultiple
        {
            get { return true; }
        }

        public override object Resolve(Type type)
        {
            return container.Resolve(type);
        }

        public override TService Resolve<TService>()
        {
            return container.Resolve<TService>();
        }

        public override void Dispose()
        {
            // Allow the container and everything it references to be disposed.
            this.container = null;
        }

        public override void Prepare()
        {
            container = new ObjectContainer(true);
            RegisterDummies(container);
            RegisterStandard(container);
            RegisterComplexObject(container);
            RegisterOpenGeneric(container);
            RegisterMultiple(container);

            container.CommitRegistrations();
        }

        private static void RegisterDummies(IObjectContainer container)
        {
            container.Register<IDummyOne, DummyOne>();
            container.Register<IDummyTwo, DummyTwo>();
            container.Register<IDummyThree, DummyThree>();
            container.Register<IDummyFour, DummyFour>();
            container.Register<IDummyFive, DummyFive>();
            container.Register<IDummySix, DummySix>();
            container.Register<IDummySeven, DummySeven>();
            container.Register<IDummyEight, DummyEight>();
            container.Register<IDummyNine, DummyNine>();
            container.Register<IDummyTen, DummyTen>();
        }

        private static void RegisterStandard(IObjectContainer container)
        {
            container.Register<ISingleton, Singleton>().In(Lifetime.Container());
            container.Register<ITransient, Transient>();
            container.Register<ICombined, Combined>();
        }

        private static void RegisterComplexObject(IObjectContainer container)
        {
            container.Register<IFirstService, FirstService>().In(Lifetime.Container());
            container.Register<ISecondService, SecondService>().In(Lifetime.Container());
            container.Register<IThirdService, ThirdService>().In(Lifetime.Container());
            container.Register<ISubObjectOne, SubObjectOne>();
            container.Register<ISubObjectTwo, SubObjectTwo>();
            container.Register<ISubObjectThree, SubObjectThree>();
            container.Register<IComplex, Complex>();
        }

        private static void RegisterOpenGeneric(IObjectContainer container)
        {
            container.RegisterOpenGeneric(typeof(IGenericInterface<>), typeof(GenericExport<>));
            container.RegisterOpenGeneric(typeof(ImportGeneric<>));
        }

        private static void RegisterMultiple(IObjectContainer container)
        {
            container.Register<ISimpleAdapter, SimpleAdapterOne>();
            container.Register<ISimpleAdapter, SimpleAdapterTwo>();
            container.Register<ISimpleAdapter, SimpleAdapterThree>();
            container.Register<ISimpleAdapter, SimpleAdapterFour>();
            container.Register<ISimpleAdapter, SimpleAdapterFive>();

            container.Register<ImportMultiple, ImportMultiple>();
        }

        //private static void RegisterInterceptor(IObjectContainer container)
        //{
        //}
    }
}